package naruto.datastructures.instruction;

/**
 * 
 * @author nacuong
 */
public abstract class Instruction<T extends gov.nasa.jpf.jvm.bytecode.Instruction> {

  int recursiveCounter;                               // counter of the recursive method containing this isntruction
  T instruction;  // bytecode instruction

  public Instruction(gov.nasa.jpf.jvm.bytecode.Instruction instruction) {
    this.instruction = (T) instruction;
  }

  public Instruction(gov.nasa.jpf.jvm.bytecode.Instruction instruction, int recursiveCounter) {
    this.instruction = (T) instruction;
    this.recursiveCounter = recursiveCounter;
  }

  public int getRecursiveCounter() {
    return this.recursiveCounter;
  }

  public T getInstruction() {
    return this.instruction;
  }

  public String getClassName() {
    return instruction.getMethodInfo().getClassName();
  }

  public String getMethodInfoName(){
    return instruction.getMethodInfo().getCompleteName();
  }

  public String getSourceCode() {
    return instruction.getSourceLine();
  }

  public int getSourceLineNumber() {
    return instruction.getLineNumber();
  }

  public int getOffset(){
    return instruction.getOffset();
  }

  public void setRecursiveCounter(int recursiveCounter) {
    this.recursiveCounter = recursiveCounter;
  }

  @Override
  public boolean equals(Object instruction) {
    boolean checkEndIf = true;
    /* if one is endif, the other must be endif as well */
    if (instruction instanceof EndIfInstruction || this instanceof EndIfInstruction)
      checkEndIf = instruction instanceof EndIfInstruction && this instanceof EndIfInstruction;

    return  checkEndIf
            && instruction instanceof Instruction
            && this.getClassName().equals(((Instruction)instruction).getClassName())
            && this.getMethodInfoName().equals(((Instruction)instruction).getMethodInfoName())
            && this.getInstruction().getOffset() == ((Instruction)instruction).getInstruction().getOffset();
  }

  public boolean isExact(Instruction instruction) {
    return this.equals(instruction) && this.getRecursiveCounter() == instruction.getRecursiveCounter();
  }
}
